package zadanie4;

import java.lang.Integer;

/**
 * Wyjatek oznaczajacy rozne bledy
 * @author ghost
 */
class Liczba2Exception extends Exception
{
	Liczba2Exception(String w) { super(w); }	
};

/**
 * Klasa zajmuje sie przeksztalcaniem liczby na rozne systemy liczbowe
 * @author ghost
 * Klasa zmienia liczby na rozne systemy liczbowe. 
 * Klasa ta dziala od 2-kowego do maksymalnie 35-kowego systemu liczbowego
 */
public class Liczba2
{
	private int min_podst = 2;
	private int max_podst = 35;
	private int decimal;
	
	/**
	 * Konstruktor bez parametrowy, gdy dojdzie do jego wywolania
	 * to zwraca on wyjatek
	 * @throws Liczba2Exception -- nie podano parametru
	 */
	Liczba2() throws Liczba2Exception
	{
		throw new Liczba2Exception("Nie podano żadnego parametru!\n");
	}

	/**
	 * Konstruktor z jednym parametrem, ustawia liczbe na podana
	 * w parametrze i uznaje ja za zapisana w 10-tnym systemie
	 * @param n -- liczba podana w 10-tnym systemie
	 */
	Liczba2(int n) 
	{
		decimal = n;
	}

	/**
	 * Konstruktor 2-parametrowy konwertuje liczbe zapisana w podanej podstawie
	 * zamieniajac ja na 10-tna
	 * @param n -- liczba do konwersji (zapisana w formie stringa)
	 * @param podstawa -- podstawa w ktorej jest zapisana liczba
	 * @throws Liczba2Exception -- wyjatek zwracajacy powod bledu
	 */
	Liczba2(String n, int podstawa) throws Liczba2Exception 
	{	
		if (min_podst < min_podst || podstawa > max_podst)
			throw new Liczba2Exception("Błędna wartość podstawy!\n");

		boolean fail = false;
		for (int i = 0; i < n.length() ; ++i)
		{
			if (podstawa <= 10 && n.charAt(i) - 48 >= podstawa)//jeśli jest większa lub równa podstawie
			{
				fail = true;
				i += n.length();
			}
			else
			{
				if (n.charAt(i) > (char)('A' - 10 + podstawa -1))//jeśli to jest niedozwolona litera
				{
					fail = true;
					i += n.length();
				}
			}
		}
		if (fail)
			throw new Liczba2Exception("Podana przez ciebie liczba nie jest zapisywalna w podanej przez ciebie podstawie!\n");
		
		if (podstawa == 10)//jeśli jest w systemie dziesiątkowym to:
		{
			try
			{
				decimal = Integer.parseInt(n);//parsuj na int-a
			}
			catch(NumberFormatException e)//jeśli zawiera litery nie tylko cyfry
			{
				System.out.println("Podana przez ciebie wartosc nie jest w systemie dziesiętnym!\n");
			}
		}
		else	//jeśli nie jest w dziesiątkowym
		{
			int zakres = n.length();
			if (podstawa < 10)//jeśli podstawa jest mniejsza od 10
			{
				decimal = 0;
				for (int i = 0, j = zakres - 1; i < zakres; ++i, --j)
				{
					decimal += ((n.charAt(j) - 48) * Math.pow(podstawa, i));
				}
			}
			else	//jeśli może zawierać jakieś litery
			{
				decimal = 0;
				for (int i = 0, j = zakres - 1; i < zakres; ++i, --j)
				{
					if (n.charAt(j) < 58)//jeśli to cyfra to zwykła zamiana
					{
						decimal += ((n.charAt(j) - 48) * Math.pow(podstawa, i));
					}
					else//jeśli to litera
					{
						decimal += (( 10 + (n.charAt(j) - 65)) * Math.pow(podstawa, i));
					}
				}
			}
		}
	}

	/**
	 * Funkcja konwertujaca decimal na podana podstawe
	 * @param podstawa -- podstawa na ktora ma byc zamieniona liczba
	 * @return -- wynik (liczba po konwersji)
	 * @throws Liczba2Exception -- jesli wystapil blad konwersji
	 */
	public String zapis(int podstawa) throws Liczba2Exception 
	{ 
		if (!(podstawa < min_podst || podstawa > max_podst))
		{
			String wynik ="";
			String odwrocony = "";
			try
			{
				int decimalx = decimal;
				if (decimal == 0)
					return "0";
				int modulo;
			
				int temp = decimal;
			
				while (decimalx != 0)
				{
					char temporary;
					temp = decimalx;
					decimalx /= podstawa;
					modulo = temp - (podstawa*decimalx);
			
					if (modulo >= 10)
						temporary = (char)(modulo + 55);
					//	wynik.replace(wynik.charAt(i), (char)(modulo + 55));
					//	wynik = (char)(modulo + 55);
					else
						temporary = (char)('0' + modulo);
					//	wynik.replace(wynik.charAt(i), (char)('0' + modulo));
					//	wynik = (char)('0' + modulo);
					wynik += temporary;
				}
				odwrocony = new StringBuffer(wynik).reverse().toString();
			}	
			catch (NumberFormatException e)
			{
				System.out.println("Błędne dane!");
			}
		
			return odwrocony;
		}
		else throw new Liczba2Exception("Podana przez ciebie podstawa nie jest prawidłowa!\nBłąd w wywołaniu funkcji!\n");
	}

	/**
	 * Funkcja sprawdzająca czy nie przekroczono maksymalnego rozmiaru int-a
	 * @param tab -- liczba do sprawdzenia(zapisana w formie stringa)
	 * @param podstawa -- podstawa liczby
	 * @throws Liczba2Exception -- liczba wieksza niz zakres int-a
	 */
	void czy_sie_miesci(String tab, int podstawa) throws Liczba2Exception //funkcja sprawdzająca czy nie przekroczono maksymalnego rozmiaru int-a
	{
		if (podstawa > (min_podst - 1) && podstawa < (max_podst + 1))
		{
			int temp = decimal;
			decimal = Integer.MAX_VALUE;
			int i = 0;//licznik powtórzeń pętli
			String zakres_maksymalny = zapis(podstawa);
			decimal = temp;

			if (tab.length() == zakres_maksymalny.length())//jeśli liczba cyfr jest równa liczbie cyfr w maksymalnym incie
			{
				while (i <= zakres_maksymalny.length() - 1)//dopóki licznik jest mniejszy od maksymalnego indeksu zakresu int-a
				{
					if (tab.charAt(i) > zakres_maksymalny.charAt(i))//jeśli odpowiadające sobie liczby są nie równe i jedna jest większa od drugiej
						throw new Liczba2Exception("Za dużo znaków!\n");
					else if (tab.charAt(i) == zakres_maksymalny.charAt(i) )
						++i;//to przejdź do następnego elementu
					else if (tab.charAt(i)  < zakres_maksymalny.charAt(i) )//jeśli odpowiadające sobie liczby są nie równe i jedna jest mniejsza od drugiej	
						i += zakres_maksymalny.length();//przerwij pętle
				}
			}
			else if (tab.length() > zakres_maksymalny.length())
				throw new Liczba2Exception("Za dużo znaków!\n");
		}
	}
}
